1"use client";
2
3
15import { useCallback } from "react";
16import { useParams } from "next/navigation";
17import { Activity, ArrowUpRight, Loader2 } from "lucide-react";
18import { workspaceActivity } from "@/lib/api";
19import { useWorkspace } from "@/hooks/use-workspace";
20import { ActivityFeed } from "@/components/activity/activity-feed";
21import type { ActivityRow } from "@/lib/types";
22
23export default function SpaceActivityPage() {
24 const params = useParams<{ workspace: string }>();
25 const slugOrId = params?.workspace ?? "";
26 const { data: ws, isLoading } = useWorkspace(slugOrId);
27
28 const fetchPage = useCallback(
29 (cursor?: string) => workspaceActivity(ws?.id ?? "", { cursor, limit: 30 }),
30 [ws?.id]
31 );
32
33
34
35
36 const hrefFor = useCallback((row: ActivityRow): string | null => {
37 if (!ws) return null;
38 if (row.pageId) return `/w/${ws.id}/page/${row.pageId}`;
39 if (row.resourceType === "database") return `/w/${ws.id}/databases/${row.resourceId}`;
40 return null;
41 }, [ws]);
42
43 return (
44 <div className="mx-auto max-w-2xl px-6 py-8">
45 <div className="mb-5 flex items-center gap-2">
46 <Activity className="size-5 text-muted-foreground" aria-hidden />
47 <h1 className="text-xl font-semibold">Activity</h1>
48 </div>
49 <p className="mb-4 text-sm text-muted-foreground">
50 What happened in {ws?.name ?? "this space"}.{" "}
51 <a href="/activity" className="inline-flex items-center gap-1 text-primary hover:underline">
52 My activity <ArrowUpRight className="size-3" aria-hidden />
53 </a>
54 </p>
55
56 {isLoading || !ws ? (
57 <p className="flex items-center gap-2 py-8 text-sm text-muted-foreground" role="status">
58 <Loader2 className="size-4 animate-spin" aria-hidden /> Loading space…
59 </p>
60 ) : (
61 <ActivityFeed fetchPage={fetchPage} hrefFor={hrefFor} emptyMessage="No activity in this space yet." />
62 )}
63 </div>
64 );
65}
66